﻿using ElasticSearchTest.Common;
using ElasticSearchTest.Model;
using Nest;
using NPOI.SS.Formula.Functions;
using PMS.Search.Domain.Common;
using PMS.Search.Domain.Entities;
using PMS.Search.Domain.QueryModel;
using PMS.Search.Elasticsearch;
using PMS.Search.Elasticsearch.Model;
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using static ElasticSearchTest.Common.BatchHelper;

namespace ElasticSearchTest
{
    public class CdnLogEsService
    {
        private readonly EsClient _client;
        private readonly EsIndexConfig.Index _index = EsIndexConfig.Instance.CdnLogIndex;

        public CdnLogEsService(EsClient client)
        {
            _client = client;
        }
        public void Test()
        {
            //var resp = CreateIndex();
        }


        public async Task<List<(string, long)>> SearcgPathAsync(IEnumerable<string> imgs)
        {
            var list = new List<(string, long)>();
            foreach (var item in imgs)
            {
                var total = await SearchAsync(Imgs(item).ToArray());
                list.Add((item, total));
            }
            return list;
        }
        public List<string> Imgs(string img)
        {
            var imgs = new List<string>();
            if (img == null)
            {
                return imgs;
            }

            //https://cos.sxkid.com/images/libimage/9121e57f-41d8-48ae-b36f-b4a9c3a0bed8.jpg
            var index = "https://cos.sxkid.com/".Length;


            //libimage/9121e57f-41d8-48ae-b36f-b4a9c3a0bed8.jpg
            var path = img.Substring(index);

            imgs.Add(img);
            imgs.Add(path);
            imgs.Add("/" + path);
            imgs.Add("//" + path);
            return imgs;
        }


        public async Task<long> SearchAsync(string[] imgs)
        {
            int from = 0;
            int size = 0;
            var search = new SearchDescriptor<CdnLog>()
                .Index(new string[] { _index.SearchIndex })
                .From(from)
                .Size(size);

            var mustQuerys = new List<Func<QueryContainerDescriptor<CdnLog>, QueryContainer>>()
            {
                q=> q.Terms(t => t.Field("path").Terms(imgs))
            };

            search.Query(q => q.Bool(b => b.Must(mustQuerys)));

            var result = await _client.GetClient().SearchAsync<CdnLog>(search);
            var total = result.Total;
            return total;
        }


        public async Task<BulkResponse> AddOrUpdateAsync(IEnumerable<CdnLog> entities)
        {
            var createResponse = await _client.GetClient()
                .BulkAsync(b =>
                    b.IndexMany(entities, (o, entity) =>
                        o.Index(_index.SearchIndex).Document(entity))
                );
            return createResponse;
        }

        public async Task AddBatchAsync(IEnumerable<CdnLog> entities)
        {
           await new Batch<CdnLog>(entities, 10000).RunAsync(async items =>
            {
                var resp = await AddOrUpdateAsync(items);
                await Task.Delay(100);
            });
        }


        public CreateIndexResponse CreateIndex()
        {
            var resp = _client.GetClient().Indices.Delete(_index.Name);
            var createIndexResponse = _client.GetClient().Indices.Create(_index.Name, c => c
                //.Aliases(ad => ad.Alias(_index.Alias))
                .Settings(s => s
                    .Setting("max_ngram_diff", 20)
                    .Setting("max_result_window", 500000)
                    .Analysis(AnalyzeBuilder.GetAnalysis())
                )
                .Map<CdnLog>(mm => mm
                .Dynamic(false)
                   .Properties(p => p
                       .Keyword(t => t.Name(n => n.referer))
                       .Keyword(t => t.Name(n => n.path))
                   )
               )
            );
            return createIndexResponse;
        }
    }
}
